import axios from 'axios'
import { Message } from 'element-ui'
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'
import router from '@/router'

// NProgress 配置
NProgress.configure({ 
  showSpinner: false, // 禁用进度环
  minimum: 0.2, // 最小百分比
  easing: 'ease',
  speed: 500
})

/**
 * 环境配置
 */
const getBaseURL = () => {
  if (process.env.NODE_ENV === 'development') {
    return '/api'
  } else if (process.env.NODE_ENV === 'production') {
    return 'https://bbgy.cpzsyun.com:82/ryapi/gardenFoster'
  }
  return '/api'
}

/**
 * 创建 axios 实例
 */
const service = axios.create({
  baseURL: getBaseURL(),
  timeout: 20000, // 请求超时时间
  headers: {
    'Content-Type': 'application/json;charset=UTF-8'
  },
  withCredentials: false // 跨域请求时是否需要凭证
})

/**
 * 请求拦截器
 */
service.interceptors.request.use(
  config => {
    // 开启进度条
    NProgress.start()
    
    // 添加 token
    const token = sessionStorage.getItem('token')
    if (token) {
      config.headers['token'] = token
    }
    
    // 处理 GET 请求参数，避免缓存
    if (config.method === 'get') {
      config.params = {
        ...config.params,
        _t: Date.now()
      }
    }
    
    return config
  },
  error => {
    // 请求错误处理
    NProgress.done()
    console.error('请求拦截器错误:', error)
    return Promise.reject(error)
  }
)

/**
 * 响应拦截器
 */
service.interceptors.response.use(
  response => {
    NProgress.done()
    
    const res = response.data
    
    // 文件下载特殊处理
    const contentType = response.headers['content-type'] || ''
    if (response.config.responseType === 'blob' || contentType.includes('application/octet-stream')) {
      return response
    }
    
    // 根据返回的状态码做相应处理
    if (res.code === 200) {
      return res
    } else if (res.code === 401) {
      // 未授权，跳转登录
      Message.error(res.msg || '登录已过期，请重新登录')
      sessionStorage.clear()
      router.push('/login')
      return Promise.reject(new Error(res.msg || '未授权'))
    } else if (res.code === 403) {
      // 无权限
      Message.error(res.msg || '无权限访问')
      return Promise.reject(new Error(res.msg || '无权限'))
    } else if (res.code === 500) {
      // 服务器错误
      Message.error(res.msg || '服务器内部错误')
      return Promise.reject(new Error(res.msg || '服务器错误'))
    } else {
      // 其他错误
      Message.error(res.msg || '请求失败')
      return Promise.reject(new Error(res.msg || '请求失败'))
    }
  },
  error => {
    NProgress.done()
    
    console.error('响应拦截器错误:', error)
    
    // 处理不同类型的错误
    if (error.response) {
      const { status, data, config } = error.response
      
      // 文件下载错误特殊处理
      if (config.responseType === 'blob') {
        Message.error('文件下载失败')
        return Promise.reject(error)
      }
      
      switch (status) {
        case 400:
          Message.error(data.msg || '请求参数错误')
          break
        case 401:
          Message.error('登录已过期，请重新登录')
          sessionStorage.clear()
          router.push('/login')
          break
        case 403:
          Message.error('无权限访问')
          break
        case 404:
          Message.error('请求的资源不存在')
          break
        case 500:
          Message.error('服务器内部错误')
          break
        case 502:
          Message.error('网关错误')
          break
        case 503:
          Message.error('服务不可用')
          break
        case 504:
          Message.error('网关超时')
          break
        default:
          Message.error(data.msg || `请求失败 (${status})`)
      }
    } else if (error.request) {
      // 请求已发出，但没有收到响应
      if (error.message.includes('timeout')) {
        Message.error('请求超时，请稍后重试')
      } else if (error.message.includes('Network Error')) {
        Message.error('网络连接失败，请检查网络')
      } else {
        Message.error('服务器无响应，请稍后重试')
      }
    } else {
      // 请求配置出错
      Message.error('请求配置错误')
    }
    
    return Promise.reject(error)
  }
)

/**
 * 封装请求方法
 * @param {Object} options - axios 配置项
 * @returns {Promise}
 */
export const request = (options) => {
  return service(options)
}

/**
 * GET 请求
 * @param {String} url - 请求地址
 * @param {Object} params - 请求参数
 * @param {Object} config - axios 配置
 */
export const get = (url, params = {}, config = {}) => {
  return service({
    method: 'get',
    url,
    params,
    ...config
  })
}

/**
 * POST 请求
 * @param {String} url - 请求地址
 * @param {Object} data - 请求数据
 * @param {Object} config - axios 配置
 */
export const post = (url, data = {}, config = {}) => {
  return service({
    method: 'post',
    url,
    data,
    ...config
  })
}

/**
 * PUT 请求
 * @param {String} url - 请求地址
 * @param {Object} data - 请求数据
 * @param {Object} config - axios 配置
 */
export const put = (url, data = {}, config = {}) => {
  return service({
    method: 'put',
    url,
    data,
    ...config
  })
}

/**
 * DELETE 请求
 * @param {String} url - 请求地址
 * @param {Object} params - 请求参数
 * @param {Object} config - axios 配置
 */
export const del = (url, params = {}, config = {}) => {
  return service({
    method: 'delete',
    url,
    params,
    ...config
  })
}

/**
 * 文件上传
 * @param {String} url - 上传地址
 * @param {FormData} data - 文件数据
 * @param {Function} onProgress - 上传进度回调
 */
export const upload = (url, data, onProgress) => {
  return service({
    method: 'post',
    url,
    data,
    headers: {
      'Content-Type': 'multipart/form-data'
    },
    onUploadProgress: progressEvent => {
      if (onProgress && typeof onProgress === 'function') {
        const percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total)
        onProgress(percentCompleted)
      }
    }
  })
}

/**
 * 文件下载
 * @param {String} url - 下载地址
 * @param {Object} params - 请求参数
 * @param {String} filename - 文件名
 */
export const download = (url, params = {}, filename = '') => {
  return service({
    method: 'get',
    url,
    params,
    responseType: 'blob'
  }).then(response => {
    const blob = new Blob([response.data])
    const downloadUrl = window.URL.createObjectURL(blob)
    const link = document.createElement('a')
    link.href = downloadUrl
    
    // 从响应头获取文件名或使用传入的文件名
    const contentDisposition = response.headers['content-disposition']
    if (contentDisposition) {
      const filenameMatch = contentDisposition.match(/filename="?(.+)"?/)
      if (filenameMatch && filenameMatch[1]) {
        filename = decodeURIComponent(filenameMatch[1])
      }
    }
    
    link.download = filename || `download_${Date.now()}`
    document.body.appendChild(link)
    link.click()
    document.body.removeChild(link)
    window.URL.revokeObjectURL(downloadUrl)
    
    return response
  }).catch(error => {
    Message.error('文件下载失败')
    return Promise.reject(error)
  })
}

/**
 * 并发请求
 * @param {Array} requests - 请求数组
 */
export const all = (requests) => {
  return axios.all(requests)
}

/**
 * 取消请求
 */
const CancelToken = axios.CancelToken
export const createCancelToken = () => {
  let cancel
  const token = new CancelToken(c => {
    cancel = c
  })
  return { token, cancel }
}

// 默认导出
export default service